#!/usr/bin/env python
# -*- coding: utf8 -*-

"""
An python class implement BlogoSerV server side

"""

# load modules
import modules

# call example
# self.HOOKLIST['login'][0]( self.HOOKLIST['login'][1], ['', ''] )

class BlogoSerV( ):
  """
>>> import liblm
>>> cc = liblm.BlogoSerV( )

# trying "blind" call... and get error
>>> cc.methodCall( 'test', [] )
(3, None)
 ^             == cc.R_NOTFOUND

# list all loaded modules
>>> cc.listModules( )
['mod_account']

# list all available methods
>>> cc.listMethods( )
['login', 'logout']

# get blacklisted methods
>>> cc.HOOKBLACKLIST
[]
>>> cc.methodCall( 'logout', [] )
(0, (0, []))
 ^          == cc.R_OK
     ^      == method result code
        ^^  == method result list / answer /
  
  """

  def __init__( self ):

    # define const
    self.R_OK         = 0
    self.R_BLACKLIST  = 1
    self.R_ERROR      = 2
    self.R_NOTFOUND   = 3

    # init auth methods
    #self.MK_AUTH  = None  # LOGIN
    #self.CHK_AUTH = None  # CHK_IS_LOGIN
    #self.DE_AUTH  = None  # LOGOUT

    # fill loaded module list
    # MODLIST = [ ( <mod_name>, <class_address>, <obj_class_address> ), ... ]
    self.MODLIST = [ (lm, modules.__dict__[lm], modules.__dict__[lm]() ) for lm in dir(modules) if lm.startswith( 'mod_' ) ]
  
    # fill action list
    # HOOKLIST = { <method_name>:( <class_address>, <method_class_address> ), ... }
    self.HOOKLIST = {}
    for lm in self.MODLIST:
      for method in dir(lm[1]):

        if method.startswith( 'do_' ):
          self.HOOKLIST[method.replace('do_', '', 1)] = ( lm[1].__dict__[method], lm[2] )

#        elif method == 'mk_auth':
#          self.MK_AUTH  = lm[2]
#
#        elif method == 'chk_auth':
#          self.CHK_AUTH = lm[2]
#
#        elif method == 'de_auth':
#          self.DE_AUTH  = lm[2]

    # make HOOKBLACKLIST  = []
    self.HOOKBLACKLIST    = []

    # make NO_AUTH_REQUIRED list == []
    self.NO_AUTH_REQUIRED = [ 'login', 'version', 'fingerprint' ]

  
  def listModules( self ):
    return [ item[0] for item in self.MODLIST ]
  
  def listMethods( self ):
    return [ item for item in self.HOOKLIST.keys() ]

  def methodCall( self, methodName, authContext, args ): # ret ( <err_code>, <result>=[] )
    """Try to call method from loaded modules"""

    if not type( authContext ) is tuple or not type( args ) is list:
      raise( Exception('Function takes methodName as first argument, authContext tuple as second and args list as third') )
  
    if   methodName in self.HOOKBLACKLIST:
      return ( self.R_BLACKLIST, [{'errcode':self.R_BLACKLIST, 'errdesc':'Named method is in BLACKLIST'}] )
  
    elif self.HOOKLIST.has_key( methodName ):
      return ( self.R_OK, self.HOOKLIST[ methodName ][ 0 ]( self.HOOKLIST[ methodName ][ 1 ], authContext, args ) )
  
    else:
      return ( self.R_NOTFOUND, [{'errcode':self.R_NOTFOUND, 'errdesc':'Named method is NOT SUPPORTED'}] )


